package br.ufmg.ubicomp.droidguide.communication;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import br.ufmg.ubicomp.droidguide.common.DroidGuideConfigurationManager;
import br.ufmg.ubicomp.droidguide.eventservice.enums.EventType;
import br.ufmg.ubicomp.droidguide.eventservice.event.DroidGuideEvent;
import br.ufmg.ubicomp.droidguide.eventservice.event.ServiceEvent;
import br.ufmg.ubicomp.droidguide.eventservice.event.UserEvent;
import br.ufmg.ubicomp.droidguide.utils.DateUtil;
import br.ufmg.ubicomp.droidguide.utils.RequestUtil;

public class EventServiceCommunication extends CommunicationService{
	
	public static final String BASE_URL = DroidGuideConfigurationManager.getInstance().getData("server") + 
		"eventservice/process?operation=";
	
	public static Collection<DroidGuideEvent> listUserEvents(String dgKey) throws Exception {
		String url = BASE_URL + "list&droidGuideUser_key="+dgKey;
		
		NodeList entities = RequestUtil.executeUrlDOM(url); 
			//processRequest(url);
		
		return getEventObjects(entities);		
	}

	private static Collection<DroidGuideEvent> getEventObjects(NodeList entities) throws ParseException {
		ArrayList<DroidGuideEvent> events = new ArrayList<DroidGuideEvent>();		
		
		DroidGuideEvent event = null;
		for (int i = 0; i < entities.getLength(); i++) {
			Node entityEntry = entities.item(i);
			
			if (entityEntry instanceof Element) {
				Element entityElement = (Element) entityEntry;
				
				if (entityElement.getAttribute("kind").equals("UserEvent")) {
					event = getUserEventObject(entityElement);
				} else if (entityElement.getAttribute("kind").equals("ServiceEvent") ||
						entityElement.getAttribute("kind").equals("ServerEvent"))
				{
					event = getServerEventObject(entityElement);
				}
				if (event != null)
					events.add(event);
			}
		}								
		
		return events;
	}

	private static UserEvent getUserEventObject(Element entityElement) throws ParseException {
		UserEvent event = new UserEvent();
		event.setKey(entityElement.getAttribute("key"));
		
		NodeList properties = entityElement.getChildNodes();
		
		for (int j = 0; j < properties.getLength(); j++) {
			Node propertyEntry = properties.item(j);
			
			if (propertyEntry instanceof Element) {
				Element propertyElement = (Element) propertyEntry;
				
				Text textNode = (Text) propertyElement.getFirstChild();
				String text = textNode.getData().trim();
				
				if (propertyElement.getTagName().equals("property")) {
					String attributeName = propertyElement.getAttribute("name");
					if (attributeName.equals("data")) {
						event.setData(text);
					} else if (attributeName.equals("source")) {
						//TODO: Broken. Waiting an object, but receiving a string.
						//event.setSource();
					} else if (attributeName.equals("droidGuideUser_key")) {
						event.setDroidGuideUserKey(text);
					} else if (attributeName.equals("datetime")) {
						Calendar c = DateUtil.parseXmlDateTime(text);
						event.setDateTime(c);
					} else if (attributeName.equals("type")) {
						if (text.equals("location")) {
							event.setType(EventType.LOCATION);
						} else if (text.equals("user")) {
							event.setType(EventType.USER);
						} else if (text.equals("device")) {
							event.setType(EventType.DEVICE);
						} else if (text.equals("connectivity")) {
							event.setType(EventType.CONNECTIVITY);
						} else if (text.equals("time")) {
							event.setType(EventType.TIME);
						} else if (text.equals("weather")) {
							event.setType(EventType.WEATHER);
						} else if (text.equals("profile")) {
							event.setType(EventType.PROFILE);
						} else if (text.equals("activity")) {
							event.setType(EventType.ACTIVITY);
						}
					}
				}
			}
		}
		return event;
	}
	
	private static ServiceEvent getServerEventObject(Element entityElement) throws ParseException {
		ServiceEvent event = new ServiceEvent();
		event.setKey(entityElement.getAttribute("key"));
		
		NodeList properties = entityElement.getChildNodes();
		
		for (int j = 0; j < properties.getLength(); j++) {
			Node propertyEntry = properties.item(j);
			
			if (propertyEntry instanceof Element) {
				Element propertyElement = (Element) propertyEntry;
				
				Text textNode = (Text) propertyElement.getFirstChild();
				String text = textNode.getData().trim();
				
				if (propertyElement.getTagName().equals("property")) {
					String attributeName = propertyElement.getAttribute("name");
					if (attributeName.equals("data")) {
						event.setData(text);
					} else if (attributeName.equals("source")) {
						//TODO: Broken. Waiting an object, but receiving a string.
						//event.setSource();
					} else if (attributeName.equals("droidGuideUser_key")) {
						event.setDroidGuideUserKey(text);
					} else if (attributeName.equals("datetime")) {
						//TODO: parse date
						Calendar c = DateUtil.parseXmlDateTime(text);
					} else if (attributeName.equals("state"))
					{
						event.setState(text);
					} else if (attributeName.equals("type"))
					{
						event.setType(text);
					}  else if (attributeName.equals("userToService_key"))
					{
						event.setUsertoServiceKey(text);
					}
				}
			}
		}
		return event;
	}
	
	public static Collection<DroidGuideEvent> save(String userKey, String type, String source, String data) throws Exception {
		String url = BASE_URL + "save&";
		
		url = url + "droidGuideUser_key=" + userKey;
		url = url + "&type=" + type;
		url = url + "&source=" + source;
		url = url + "&data=" + data;
		
		NodeList entities = RequestUtil.executeUrlDOM(url); 
			//processRequest(url);
		
		Collection<DroidGuideEvent> userEvents = getEventObjects(entities);
		
		return userEvents;
		
	}

	public static Collection<DroidGuideEvent> read(String userKey) throws Exception {
		String url = BASE_URL + "getServerEvents&";
		
		url = url + "droidGuideUser_key=" + userKey;
		
		NodeList entities = RequestUtil.executeUrlDOM(url); 
			//processRequest(url);
		
		Collection<DroidGuideEvent> userEvents = getEventObjects(entities);
		
		return userEvents;
		
	}

//	public static void consume(String serviceKey) throws Exception {
//		String url = BASE_URL + "consume&";
//		
//		url = url + "serv_evt_key=" + serviceKey;
//		
//		/* Make request */
//		DefaultHttpClient client = new DefaultHttpClient();
//		HttpGet method = new HttpGet(url);		
//		HttpResponse response =  client.execute(method);
//		HttpEntity entity = response.getEntity();
//		InputStream inStream = entity.getContent();
//		
//		// Response not working yet.
//	}
}
